package restful

import (
	"fmt"
	"log"
	"net/http"
	"os"
	"path/filepath"
	"strings"

	"example.com/crawler/crawl"
	"github.com/gin-gonic/gin"
)

func StartWebServer() {
	router := gin.Default()
    router.GET("/cjmx", getCJMX)
	router.GET("/cjmx/list/:id", listCJMXByID)
    router.Run("localhost:8085")
}

type stock_cjmx struct {
	Id string `form:"id"`
	Time string `form:"time"` // 20221024
}

const DEBUG = false

func getCJMX(ctx *gin.Context) {
	var cjmx stock_cjmx
	if ctx.ShouldBind(&cjmx) != nil {
		ctx.String(404, "Not valid param")
		return
	}
	if cjmx.Id != "" && cjmx.Time != "" {
		// download file
		// Note: 原始的股票文件在股票代码中有个前缀1
		fileName := "cjmx_" + cjmx.Time + "_1" + cjmx.Id + ".xls"
		targetPath := filepath.Join(crawl.OUTPUT_DIR, fileName)
		log.Println("Download file", targetPath)
		if DEBUG {
			// do not download
			ctx.String(200, "Success")
			return
		}
		if exist, _ := PathExists(targetPath); !exist {
			log.Println("File not exist", targetPath)
			ctx.IndentedJSON(http.StatusNotFound, gin.H{"message": fmt.Sprintf("File not found. Update the stock %s", cjmx.Id)})
			// ctx.String(404, fmt.Sprintf("File not found. You can update the stock %s data", cjmx.Id))
			return
		}
		//This ckeck is for example, I not sure is it can prevent all possible filename attacks - will be much better if real filename will not come from user side. I not even tryed this code
		if !strings.HasPrefix(filepath.Clean(targetPath), crawl.OUTPUT_DIR) {
			ctx.String(403, "Look like you attacking me")
			return
		}
		//Seems this headers needed for some browsers (for example without this headers Chrome will download files as txt)
		ctx.Header("Content-Description", "File Transfer")
		ctx.Header("Content-Transfer-Encoding", "binary")
		ctx.Header("Content-Disposition", "attachment; filename="+fileName )
		ctx.Header("Content-Type", "application/octet-stream")
		ctx.File(targetPath)
	} else if cjmx.Time == "" {
		// retrieve xls
		log.Printf("Retriving the stock %s cjmx\n", cjmx.Id)
		go crawl.Crawling(cjmx.Id)
		ctx.String(200, "Success")
	}
}

func PathExists(path string) (bool, error) {
	_, err := os.Stat(path)
	if err == nil {
		return true, nil
	}
	if os.IsNotExist(err) {
		return false, nil
	}
	return false, err
}

func listCJMXByID(ctx *gin.Context) {
	stockID := ctx.Param("id")
	log.Println("search", stockID)
	filenames := []string{}
	err := filepath.Walk(crawl.OUTPUT_DIR, func(path string, info os.FileInfo, err error) error {
		if info.IsDir() {
			return nil
		}
		if strings.Contains(path, stockID) {
			filenames = append(filenames, info.Name())
		}
		return nil
	})
	if err != nil {
        ctx.String(403, err.Error())
    }
	ctx.IndentedJSON(http.StatusOK, filenames)
}